`include "defines.v"
module rdAXI(
  input clk,
  input rst_n,

  input  rd_addr_valid_i,
  input  [`ADDR_W-1:0]rd_addr_i,
  output rd_data_valid_o,
  output [127:0]rd_data_o,

  input                               axi_ar_ready     ,
  output                              axi_ar_valid     ,
  output [`AXI_ADDR_WIDTH-1:0]        axi_ar_bits_addr ,
  output [2:0]                        axi_ar_bits_prot ,
  output [`AXI_ID_WIDTH-1:0]          axi_ar_bits_id   ,
  output [`AXI_USER_WIDTH-1:0]        axi_ar_bits_user ,
  output [7:0]                        axi_ar_bits_len  ,
  output [2:0]                        axi_ar_bits_size ,
  output [1:0]                        axi_ar_bits_burst,
  output                              axi_ar_bits_lock ,
  output [3:0]                        axi_ar_bits_cache,
  output [3:0]                        axi_ar_bits_qos  ,

  output                              axi_r_ready      ,
  input                               axi_r_valid      ,
  input  [1:0]                        axi_r_bits_resp  ,
  input  [`AXI_DATA_WIDTH-1:0]        axi_r_bits_data  ,
  input                               axi_r_bits_last  ,
  input  [`AXI_ID_WIDTH-1:0]          axi_r_bits_id    ,
  input  [`AXI_USER_WIDTH-1:0]        axi_r_bits_user  
);
wire isMMIO = rd_addr_valid_i &  ~rd_addr_i[`ADDR_W-1] ;
// handshake signal 
wire ar_hs  = axi_ar_ready && axi_ar_valid ;
wire r_hs   = axi_r_ready  && axi_r_valid  ;

reg [1:0] state;
parameter IDLE = 2'd0,
          AR   = 2'd1,
          R    = 2'd2,
          WAIT = 2'd3;
always@(posedge clk or negedge rst_n)
  if(~rst_n)
    state <= IDLE;
  else begin
    case(state)
      IDLE:if(rd_addr_valid_i) state <= AR; 
      AR  :if(ar_hs) state <= R; 
      R   :if(r_hs && axi_r_bits_last) state <= WAIT; //else if(flush || flushR ) state <= AR;
      WAIT:state <= IDLE;
      default:state <= IDLE;
    endcase
  end

always@(*)begin
  if(axi_r_ready  && axi_r_valid && (axi_r_bits_resp != 2'b00))begin
    $display("rd recv error resp");
    $finish;
  end
end

// MMIO 访问32B对齐  Cache 访问 128B对齐
assign axi_ar_valid      = state == AR;
assign axi_ar_bits_addr  = isMMIO ?  rd_addr_i : {rd_addr_i[31:4] , 4'd0};
assign axi_ar_bits_prot  = 'd0;
assign axi_ar_bits_id    = 'd1;
assign axi_ar_bits_user  = 'd0;
assign axi_ar_bits_len   = isMMIO ? 'd0    : 'd1;
assign axi_ar_bits_size  = isMMIO ? 3'b010 : 3'b011;
assign axi_ar_bits_burst = 2'b01;
assign axi_ar_bits_lock  = 'd0;
assign axi_ar_bits_cache = 'b0010;
assign axi_ar_bits_qos   = 'd0;
assign axi_r_ready       = state == R;

// always@(posedge clk)
//   if(isMMIO)begin
//     $fwrite(32'h8000_0001, "%d %x %x ", isMMIO , axi_ar_bits_addr ,axi_ar_bits_size);
//     $fflush();
//   end

reg [127:0] buffer;
always@(posedge clk  or negedge rst_n)
  if(~rst_n)
    buffer <= 128'd0;
  else if(state == R)
    if(isMMIO)begin   // 窄传输 到上层的字符处理 根据地址映射到64位
      buffer[63:0]   <= rd_addr_i[2] ? {axi_r_bits_data[63:32],axi_r_bits_data[63:32]} :
                       {axi_r_bits_data[31:0],axi_r_bits_data[31:0]};
      // buffer[127:64] <= axi_r_bits_data;
    end else begin
      if(axi_r_bits_last)
        buffer[127:64] <= axi_r_bits_data;
      else  
        buffer[63:0]   <= axi_r_bits_data;
    end

reg data_ok;
always@(posedge clk or negedge rst_n)
  if(~rst_n)
    data_ok <= 1'b0;
  else if(r_hs && axi_r_bits_last)
    data_ok <= 1'b1;
  else
    data_ok <= 1'b0;

assign rd_data_valid_o = data_ok ;
assign rd_data_o       = buffer;
endmodule